﻿using System;

namespace CoreEx.Database.Query.Expressions
{
    /// <summary>
    /// Provides the fluent interface that targets a 'SELECT' query.
    /// </summary>
    public class DbSelectQuery : DbQuery<DbSelectExpression>
    {
        
        /// <summary>
        /// Gets the <see cref="DbQueryType"/> for this <see cref="DbQuery{TQueryExpression}"/>.
        /// </summary>
        /// <value></value>
        public override DbQueryType QueryType
        {
            get { return DbQueryType.Select; }
        }

        /// <summary>
        /// Creates a <see cref="DbOrderByExpression"/> that represents ordering the result set.
        /// </summary>
        /// <param name="expression">The <see cref="DbExpression"/> that represents an element in the 'ORDER BY' clause.</param>
        /// <param name="orderByExpressionType">Specifies the sort order direction.</param>
        /// <returns></returns>
        public DbQuery<DbSelectExpression> OrderBy(Func<DbExpressionFactory,DbExpression> expression, DbOrderByExpressionType orderByExpressionType)
        {
            var dbExpression = (DbExpression)ExpressionFactory.MakeOrderBy(orderByExpressionType, expression(ExpressionFactory));
            if (!QueryExpression.OrderByExpression.IsNull())
                dbExpression = ExpressionFactory.List(new[] { QueryExpression.FromExpression, dbExpression });
            QueryExpression.OrderByExpression = dbExpression;
            return this;
        }

        /// <summary>
        /// Creates a new <see cref="DbOrderByExpression"/> that represents an ascending ordering of the result set.
        /// </summary>
        public DbQuery<DbSelectExpression> OrderByAscending(Func<DbExpressionFactory, DbExpression> expression)
        {
            return OrderBy(expression, DbOrderByExpressionType.Ascending);
        }

        /// <summary>
        /// Creates a new <see cref="DbOrderByExpression"/> that represents an descending ordering of the result set.
        /// </summary>
        public DbQuery<DbSelectExpression> OrderByDescending(Func<DbExpressionFactory, DbExpression> expression)
        {
            return OrderBy(expression, DbOrderByExpressionType.Ascending);
        }

        /// <summary>
        /// Limits the rows return by the query.
        /// </summary>
        /// <param name="expression">The <see cref="DbExpression"/> representing a numeric expression.</param>
        /// <returns><see cref="DbQuery{TQueryExpression}"/></returns>
        public DbQuery<DbSelectExpression> Take(Func<DbExpressionFactory, DbExpression> expression)
        {
            QueryExpression.TakeExpression = expression(ExpressionFactory);
            return this;
        }

        /// <summary>
        /// Bypasses a specified number of rows in the result set.
        /// </summary>
        /// <param name="expression">The <see cref="DbExpression"/> representing a numeric expression.</param>
        /// <returns><see cref="DbQuery{TQueryExpression}"/></returns>
        public DbQuery<DbSelectExpression> Skip(Func<DbExpressionFactory, DbExpression> expression)
        {
            QueryExpression.SkipExpression = expression(ExpressionFactory);
            return this;
        }

       
    }
}
